// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


// Adapted from Apache Arrow.

#include <pollux/dwio/parquet/common/level_comparison.h>

#include <limits>

#include <melon/lang/bits.h>

namespace kumo::pollux::parquet {
    namespace {
        template<typename Predicate>
        inline uint64_t
        LevelsToBitmap(const int16_t *levels, int64_t numLevels, Predicate predicate) {
            // Both clang and GCC can vectorize this automatically with SSE4/AVX2.
            uint64_t mask = 0;
            for (int x = 0; x < numLevels; x++) {
                mask |= static_cast<uint64_t>(predicate(levels[x]) ? 1 : 0) << x;
            }
            return melon::Endian::little(mask);
        }
    } // namespace

    uint64_t
    GreaterThanBitmap(const int16_t *levels, int64_t numLevels, int16_t rhs) {
        return LevelsToBitmap(
            levels, numLevels, [rhs](int16_t value) { return value > rhs; });
    }

    MinMax FindMinMax(const int16_t *levels, int64_t numLevels) {
        MinMax out{
            std::numeric_limits<int16_t>::max(), std::numeric_limits<int16_t>::min()
        };
        for (int x = 0; x < numLevels; x++) {
            out.min = std::min(levels[x], out.min);
            out.max = std::max(levels[x], out.max);
        }
        return out;
    }
} // namespace kumo::pollux::parquet
